package org.rockyang.blockj.base.crypto;

import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.jcajce.provider.digest.Keccak;
import org.rockyang.blockj.base.utils.Numeric;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * hash 工具类
 *
 * @author yangjian
 * @since 2018-04-07 下午8:32.
 */
public class Hash {
	private Hash()
	{
	}

	/**
	 * Keccak-256 hash function.
	 *
	 * @param hexInput hex encoded input data with optional 0x prefix
	 * @return hash value as hex encoded string
	 */
	public static String sha3(String hexInput)
	{
		byte[] bytes = Numeric.hexStringToByteArray(hexInput);
		byte[] result = sha3(bytes);
		return Numeric.toHexString(result);
	}

	public static String sha256Hex(byte[] input)
	{

		return DigestUtils.sha256Hex(input);
	}

	/**
	 * Keccak-256 hash function.
	 *
	 * @param input  binary encoded input data
	 * @param offset of start of data
	 * @param length of data
	 * @return hash value
	 */
	public static byte[] sha3(byte[] input, int offset, int length)
	{
		Keccak.DigestKeccak kecc = new Keccak.Digest256();
		kecc.update(input, offset, length);
		return kecc.digest();
	}

	/**
	 * Keccak-256 hash function.
	 *
	 * @param input binary encoded input data
	 * @return hash value
	 */
	public static byte[] sha3(byte[] input)
	{
		return sha3(input, 0, input.length);
	}

	/**
	 * Keccak-256 hash function that operates on a UTF-8 encoded String.
	 *
	 * @param utf8String UTF-8 encoded string
	 * @return hash value as hex encoded string
	 */
	public static String sha3String(String utf8String)
	{
		return Numeric.toHexString(sha3(utf8String.getBytes(StandardCharsets.UTF_8)));
	}

	/**
	 * Generates SHA-256 digest for the given {@code input}.
	 *
	 * @param input The input to digest
	 * @return The hash value for the given input
	 * @throws RuntimeException If we couldn't find any SHA-256 provider
	 */
	public static byte[] sha256(byte[] input)
	{
		try {
			MessageDigest digest = MessageDigest.getInstance("SHA-256");
			return digest.digest(input);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("Couldn't find a SHA-256 provider", e);
		}
	}
}
